﻿using Cysharp.Threading.Tasks;
using DG.Tweening;
using System;
using System.Net.NetworkInformation;
using System.Threading;
using UnityEngine;
using UnityEngine.Windows;

namespace moai_kun_v2
{
    public class MainActor : Actor, IDamageable
    {
        #region Unity方法
        protected override void Update()
        {
            base.Update();
         
        }
        protected override void OnDrawGizmos()
        {
            base.OnDrawGizmos();
            DrawAttackLine();
        }
        #endregion

        #region 站立状态
        public void DoIdle() 
        {
            SetVelocityZero();
            _animator.Play(MainPlayerAnimName.IDLE);
        }

        public void StaticIdle() 
        {
            if (CanIdle()) 
            {
                DoIdle();
            }
        }

        public bool CanIdle()
        {
            return OnGrounded && !_isCrouch && !_die&&!_isAttacking;
        }
        #endregion

        #region 移动
        [Header("移动参数")]
        [SerializeField]private float _moveSpeed;
        public void SetMoveSpeed(float speed) 
        {
            _moveSpeed = speed;        
        }
        public void Move(Vector2 direction) 
        {
            if (CanMove()) 
            {
                MoveTo(direction);
            }
        }

        public bool CanMove() 
        {
            return OnGrounded&&!_isCrouch&&!_die&&!_isAttacking;
        }
        public void MoveTo(Vector2 direction)
        {
            _animator.Play(MainPlayerAnimName.WALK);
            var moveDir=new Vector2(direction.x,0);
            moveDir.Normalize();
            ShouldIfFlip((int)direction.x);
            SetVelocity(_moveSpeed,moveDir);
        }
        #endregion

        #region 跳跃
        [Header("跳跃参数")]
        [SerializeField] private float _jumpHight;//跳跃角度
        [SerializeField] private float _jumpforce;//跳跃力度
        [SerializeField] private float _drag;//空气阻力

        public void Jump() 
        {
            if (CanJump()) 
            {
                DoJump();
            }
        }

        private bool CanJump()
        {
            return OnGrounded&&!_die&&!_isAttacking;
        }
        private void DoJump() 
        {
            Vector2 jumpDir = new Vector2(0,_jumpHight);
            jumpDir.Normalize();
            SetVelocity(_jumpforce,jumpDir);
        }

        public void UpdateAirStatus(float inputX)
        {
            if(!OnGrounded&&!_die&&!_isAttacking)
            {
                ShouldIfFlip((int)inputX);
                SetVelocityX(inputX*_drag);
                _animator.Play(MainPlayerAnimName.JUMP);
            }
        }

        #endregion

        #region 攻击
        [Header("攻击")]
        [SerializeField] private float _attackInterval;
        [SerializeField] private Transform _attackPos;
        [SerializeField] private LayerMask _damageMask;
        [SerializeField] private float _attackRadius = 0.5f;
        private bool _isAttacking;
        public bool IsAttacking => _isAttacking;

        public async UniTaskVoid Attack()
        {
            if (CanAttack()) 
            {
                Debug.Log("攻击");
                PlayAnim(MainPlayerAnimName.ATTACK);
                _isAttacking = true;
                await UniTask.WhenAll(AttackDetectAsync(),AttackEndAsync());
            }
            
        }

        public bool CanAttack()
        {
            return !_isAttacking && !_die && !_isCrouch;
        }

        private async UniTask AttackDetectAsync()
        {
            while (true)
            {
                var hitInfo = Physics2D.OverlapCircle(_attackPos.position, _attackRadius, _damageMask);
                if (hitInfo != null)
                {
                    Debug.Log(hitInfo.name);
                    var target = hitInfo.GetComponent<IDamageable>();
                    AttackDetail detail = new AttackDetail();
                    detail.Direction = _direction;
                    target.TakeDamage(detail);
                }
                if (!_isAttacking)
                {
                    break;
                }
                await UniTask.Yield();
            }
        }

        private async UniTask AttackEndAsync()
        {
            await UniTask.Delay(System.TimeSpan.FromSeconds(_attackInterval));
            Debug.Log("攻击结束");
            _isAttacking = false;
        }

        private void DrawAttackLine()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireSphere(_attackPos.position, _attackRadius);
        }
        #endregion

        #region 蹲下
        private bool _isCrouch;
        public bool CanCrouch() 
        {
            return OnGrounded && !_die && !_isAttacking;
        }
        public void StartCrouch() 
        {
            if (CanCrouch()) 
            {
                SetVelocityZero();
                _isCrouch = true;
                _animator.Play(MainPlayerAnimName.CROUCH);
            }
            
        }
        public void StopCrouch()
        {
            if (_isCrouch)
            {
                _isCrouch = false;
                _animator.Play(MainPlayerAnimName.IDLE);
            }
            
        }
        #endregion

        #region 放炸弹
        [Header("放炸弹")]
        private int _bombCount=0;
        public Action<int> OnBombCountChanged;
        public int BombCount 
        {
            get => _bombCount;
            set 
            {
                if (_bombCount <= 0) 
                {
                    _bombCount = 0;
                }
                if (_bombCount != value) 
                {
                    OnBombCountChanged.Invoke(value);
                }
                _bombCount = value;
            }
        }
        private bool _hasBomb=> _bombCount > 0;
        [SerializeField] private GameObject _bombObj;
        [SerializeField] private Transform _bombTransform;
        public bool CanSetBomb() 
        {
            return _isCrouch && _hasBomb;
        }
        public void GetBomb() 
        {
            BombCount++;
        }

        public void SetBomb() 
        {
            if (CanSetBomb()) 
            {
                DoSetBomb();
            }
        }

        private void DoSetBomb()
        {
            Debug.Log("安装炸弹");
            //GameObject.Instantiate(_bombObj,_bombTransform.position,Quaternion.identity);
            BombCount--;
        }
        #endregion

        #region 死亡
        public Action OnDead;
        public Action OnDeadComplete;
        private bool _die;
        public void TakeDamage(AttackDetail detail)
        {
            Die();
        }

        private bool CanDie()
        {
            return !_die;
        }
        public void Die()
        {
            if (CanDie()) 
            {
                OnDead.Invoke();
                DoDie();
            }
        }
        [Header("死亡")]
        [SerializeField] private float _dieDuration;

        [SerializeField] private float _goHeavenDistance;
        [SerializeField] private float _goHeavenDuration;
        

        private void DoDie()
        {
            _die = true;
            SetGravityScale(0);
            SetVelocityZero();
            var sequence=DOTween.Sequence();
            sequence.AppendCallback(() => { _animator.Play(MainPlayerAnimName.DIE); });
            sequence.AppendInterval(_dieDuration);
            sequence.AppendCallback(() => { _animator.Play(MainPlayerAnimName.GO_HEAVEN); });
            sequence.Append(transform.DOMoveY(transform.position.y+_goHeavenDistance,_goHeavenDuration));
            sequence.AppendCallback(()=>OnDeadComplete?.Invoke()) ;
            sequence.Play();
        }

        public void ResetStatus()
        {
            this.gameObject.SetActive(true);
            _die = false;
            SetGravityScale(3.5f);
        }

        public void Hide()
        {
            this.gameObject.SetActive(false);
        }

        #endregion
    }
}
